package com.asurplus.common.jwt;

import com.asurplus.common.redis.RedisConst;
import com.asurplus.common.redis.RedisUtil;
import com.asurplus.common.utils.SpringContextUtils;
import com.auth0.jwt.JWT;
import com.auth0.jwt.algorithms.Algorithm;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.servlet.http.HttpServletRequest;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

/**
 * Jwt工具类，生成JWT和认证
 *
 * @author dongk
 * @date 2021-02-05 11:10:08
 */
@Slf4j
@Component
public class JwtUtil {

    @Autowired
    private RedisUtil redisUtil;

    /**
     * 密钥
     */
    private static final String SECRET = "asurplus_secret";

    /**
     * 过期时间（单位：秒）
     **/
    private static final long EXPIRATION = 1800L;

    /**
     * 生成用户token,设置token超时时间
     *
     * @param userId
     * @param password
     * @return
     */
    public String createToken(Integer userId, String account, String password) {
        Map<String, Object> map = new HashMap<>();
        map.put("alg", "HS256");
        map.put("typ", "JWT");
        String token = JWT.create()
                // 添加头部
                .withHeader(map)
                // 放入用户的id
                .withAudience(String.valueOf(userId))
                // 可以将基本信息放到claims中
                .withClaim("account", account)
                .withClaim("password", password)
                // 超时设置,设置过期的日期
                .withExpiresAt(new Date(System.currentTimeMillis() + EXPIRATION * 1000))
                // 签发时间
                .withIssuedAt(new Date())
                // SECRET加密
                .sign(Algorithm.HMAC256(SECRET));
        // 存入redis
        redisUtil.set(RedisConst.Key.API_TOKEN + token, userId, EXPIRATION);
        return token;
    }

    /**
     * 获取用户id
     */
    public Integer getUserId() {
        HttpServletRequest request = SpringContextUtils.getHttpServletRequest();
        // 从请求头部中获取token信息
        String token = request.getHeader("Authorization");
        if (StringUtils.isNotBlank(token)) {
            try {
                Object object = redisUtil.get(RedisConst.Key.API_TOKEN + token);
                if (null != object) {
                    return Integer.parseInt(object.toString());
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        // 响应状态码为401
        SpringContextUtils.getHttpServletResponse().setStatus(401);
        return null;
    }

    /**
     * 校验token并解析token
     */
    public boolean verity() {
        HttpServletRequest request = SpringContextUtils.getHttpServletRequest();
        // 从请求头部中获取token信息
        String token = request.getHeader("Authorization");
        if (StringUtils.isNotBlank(token)) {
            try {
                Object object = redisUtil.get(RedisConst.Key.API_TOKEN + token);
                if (null != object) {
                    // 刷新存活时间
                    redisUtil.setExpire(RedisConst.Key.API_TOKEN + token, EXPIRATION);
                    // 返回结果认证
                    return true;
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        // 响应状态码为401
        SpringContextUtils.getHttpServletResponse().setStatus(401);
        return false;
    }

}
